package dhadi.model;

import org.json.JSONException;
import org.json.JSONObject;

import dhadi.util.Util;

public class Move {
	
	public static final int PICK_PLACED_ON_BOARD = 0x0;

	public static final int PICK_MOVED_ON_BOARD = 0x1;

	public static final int PICK_KILLED = 0x2;

	private static final Object FIELD_SEPARATOR = ",";

	private static final Object VALUE_SEPARATOR = ":";

	private static final Object RECORD_BEGIN = "{";
	private static final Object RECORD_END = "}";
	
	private Player player;
	private Pick pick;
	private Node fromNode;
	private Node toNode;
	private String time;
	public Move(Pick pick, Player player)
	{
		this.pick = pick;
		this.player = player;
		time = Util.getFormattedDate();
	}

	public Player getPlayer() {
		return player;
	}

	public void setPlayer(Player player) {
		this.player = player;
	}

	public Pick getPick() {
		return pick;
	}

	public void setPick(Pick pick) {
		this.pick = pick;
	}

	public Node getFromNode() {
		return fromNode;
	}

	public void setFromNode(Node fromNode) {
		this.fromNode = fromNode;
	}

	public Node getToNode() {
		return toNode;
	}

	public void setToNode(Node toNode) {
		this.toNode = toNode;
	}

	public String toString() {
		return "Move [player=" + player + ", pick=" + pick + ", toNode="
				+ toNode + ", fromNode=" + fromNode /*+ ", pickFromState="
				+ pickFromState + ", pickToState=" + pickToState*/ + "]";
	}
	
	public boolean equals(Object otherMove) {
	    if (!(otherMove instanceof Move)) return false;
	    Move m = (Move)otherMove;
	    if (m.pick != null && !m.pick.equals(this.pick)) return false;
	    if (m.fromNode != null && !m.fromNode.equals(this.fromNode)) return false;
	    if (m.player != null && !m.player.equals(this.player)) return false;
	    if (m.toNode != null && !m.toNode.equals(this.toNode)) return false;
	    return true;
	}

	/**
	 * Move type is based on the following Move data
	 * 
	 * PICK_PLACED_ON_BOARD, PICK_MOVED_ON_BOARD
	 *   move.player is the player who made this move
	 *   move.pick is the pick that is moved, whose
	 *             status will be Pick.USED 
	 *   move.toNode will be non null value
	 *   move.fromNode can be null if PICK_PLACED_ON_BOARD
	 * 
	 * PICK_KILLED
	 *   move.player is the player who made this move
	 *   move.pick is the pick that is moved, whose
	 *             status will be Pick.DESTROYED
	 *   move.toNode will be null
	 *   move.fromNode will be a valid node
	 * 
	 */
	public int whatMove() {
		
		if (this.toNode != null && this.fromNode == null) 
			return Move.PICK_PLACED_ON_BOARD;
		else
		if (this.toNode == null)
				return Move.PICK_KILLED;
		else
		if (this.toNode != null && this.fromNode != null)
			return Move.PICK_MOVED_ON_BOARD;
		else
			return Move.PICK_MOVED_ON_BOARD; // This should never happen
	}

	public JSONObject toJson() throws JSONException {
		JSONObject json = new JSONObject();
		json.put("Time", this.time);
		json.put("Player", this.player.toJson());
		json.put("Pick", this.pick.toJson());
		json.put("FromNode", this.fromNode==null?"null":this.fromNode.toJson());
		json.put("ToNode", this.toNode==null?"null":this.toNode.toJson());
		return json;
	}
	
	public static Move fromJson(String jString, SerializationContext context) throws JSONException {
	    JSONObject json = new JSONObject(jString);
	    String time = json.getString("Time");
	    
	    Player player = context.board.getMatchinPlayer( 
	        Player.fromJson(json.getString("Player")));
	    
	    Pick pick = Pick.fromJson(json.getString("Pick"),context);	    
	    Node fromNode = Node.fromJson(json.getString("FromNode"), context);
	    Node toNode = Node.fromJson(json.getString("ToNode"), context);
	    
	    Move move = new Move(pick,player);
	    move.setFromNode(fromNode);
	    move.setToNode(toNode);
	    
	    return move;	    
	}

	/**
	 * Creates a Move that kills the given pick by 
	 * the currentPlayer
	 * 
	 * @param pick
	 * @param currentPlayer
	 * @return
	 */
    public static Move createKill(Pick pick, Player currentPlayer) {
        Move move = new Move(pick,currentPlayer);
        move.setFromNode(pick.getNode());
        move.setToNode(null);
        return move;
    }

    /**
     * Creates a Move that moves given pick to the given toNode
     * 
     * @param pick
     * @param player
     * @param toNode
     * @return
     */
    public static Move createOnBoardMove(Pick pick, Player player, Node toNode) {
        Move move = new Move(pick,player);
        move.setFromNode(pick.getNode());
        move.setToNode(toNode);
        return move;
    }
    
    /**
     * Creates a Move that places pick on node toNode
     * 
     * @param pick
     * @param player
     * @param toNode
     * @return
     */
    public static Move createOntoBoardMove(Pick pick, Player player, Node toNode) {
        Move move = new Move(pick,player);
        move.setFromNode(null);
        move.setToNode(toNode);
        return move;
    }
}
